/*****************************************************************************
 * @brief   SPI NAND HAL LINK
 *****************************************************************************/
#include "bsp_nand_w25n.h"
#include "nand_lut.h"

/*****************************************************************************
 * @brief   INFO
 *****************************************************************************/
uint8_t spi_nand_read_spare(uint32_t page_addr, uint8_t *dat, uint16_t Len);
uint8_t nand_power_wait(void);

/*****************************************************************************
 * @brief   hal interface link
 *****************************************************************************/
char nand_spi_dev_link(nand_lut_type *lut)
{
	dword_tt id;
	char cnt;
	uu8 st[4];

	// spi nand hal link
	lut->hal.ecc_error_get = bsp_snand_ecc_error_get;
	lut->hal.read_page = bsp_snand_read_page;
	lut->hal.read_cache = bsp_snand_q_read_cache;
	lut->hal.read_spare = spi_nand_read_spare;
	lut->hal.write_cache = bsp_snand_q_write_cache;
	lut->hal.program_exe = bsp_snand_program_exe;
	lut->hal.block_erase = bsp_snand_block_erase;
	lut->hal.init = 0;

	// chip infomation recognize
	for (cnt = 0; cnt < 5; cnt++)
	{
		// read ID
		id.uVal = 0;
		bsp_snand_read_id(id.v);

		// gd5 1Gbits
		if ((id.uVal & 0xFFFF) == 0xC8F1)
		{
			bsp_snand_info.block_total = 1024;
			bsp_snand_info.page_main_size = 2048;
			bsp_snand_info.page_spare_size = 16;
			bsp_snand_info.page_per_block = 64;

			lut->page_size = 2048 + 16;
			lut->page_main_size = 2048;
			lut->page_spare_size = 16;
			lut->page_per_block = 64;
			lut->block_per_plane = 1024;
			lut->block_total = 1024;
			lut->logic_block_amount = 1024 * 7 / 8;
			lut->keep_err_logic = 0;

			lut->hal.init = bsp_gd5_init;

			break;
		}

		// w25n 1Gbits
		else if ((id.uVal & 0xFFFFFF00) == 0x21AAEF00)
		{
			bsp_snand_info.block_total = 1024;
			bsp_snand_info.page_main_size = 2048;
			bsp_snand_info.page_spare_size = 8;
			bsp_snand_info.page_per_block = 64;

			lut->page_size = 2048 + 8;
			lut->page_main_size = 2048;
			lut->page_spare_size = 8;
			lut->page_per_block = 64;
			lut->block_per_plane = 1024;
			lut->block_total = 1024;
			lut->logic_block_amount = 1024 * 7 / 8;
			lut->keep_err_logic = 0;

			lut->hal.init = bsp_w25n_init;

			break;
		}
		else
		{
			bsp_snand_info.block_total = 1024;
			bsp_snand_info.page_main_size = 2048;
			bsp_snand_info.page_spare_size = 16;
			bsp_snand_info.page_per_block = 64;
		}
	}

	lut->hal.power_wait = nand_power_wait;

	st[0] = bsp_snand_featute_get(NAND_FEATURE_1_PROTECT);
	st[1] = bsp_snand_featute_get(NAND_FEATURE_2_CFG);
	st[2] = bsp_snand_featute_get(NAND_FEATURE_3_ST);

	if (st[0] != 0)
	{
		bsp_snand_write_enable();
		bsp_snand_featute_set(NAND_FEATURE_1_PROTECT, 0xFF, 0);
		st[0] = bsp_snand_featute_get(NAND_FEATURE_1_PROTECT);
	}

	return 0;
}

/*****************************************************************************
 * @brief   read spare.
 * @param   page_addr, dat, Len
 * @return  none
 *****************************************************************************/
uint8_t spi_nand_read_spare(uint32_t page_addr, uint8_t *dat, uint16_t Len)
{
	bsp_snand_read_page(page_addr);

	bsp_snand_q_read_cache(bsp_snand_info.page_main_size, dat, Len);

	return 0;
}
